﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Chapter15
{
    using System.Reflection;
    using System.IO;

    partial class Program
    {
        internal static void Begin(Action action, bool active = false)
        {
            if (active)
            {
                Console.WriteLine("开始演示：");
                action();
                Console.WriteLine("演示完毕：");
                Console.ReadLine();
            }
        }

        internal static void C01()
        {
            {
                Console.WriteLine(Enum.GetUnderlyingType(typeof(Color)));
                Color c = Color.Blue;
                Console.WriteLine(c);
                Console.WriteLine(c.ToString());
                Console.WriteLine(c.ToString("G"));
                Console.WriteLine(c.ToString("D"));
                Console.WriteLine(c.ToString("X"));
            }
            {
                Color[] colors = (Color[])Enum.GetValues(typeof(Color));
                Console.WriteLine("Number of symbols definded: " + colors.Length);
                Console.WriteLine("Value\tSymbol\n------\t------");
                foreach (Color c in colors)
                {
                    Console.WriteLine("{0,5:D}\t{0:G}", c);
                }
            }
            {
                Color c = (Color)Enum.Parse(typeof(Color), "orange", true);
                Console.WriteLine(c);
                Enum.TryParse<Color>("1", false, out c);
                Console.WriteLine(c);
                Enum.TryParse<Color>("23", false, out c);
                Console.WriteLine(c);
                Console.WriteLine(Enum.IsDefined(typeof(Color), (byte)1));
                Console.WriteLine(Enum.IsDefined(typeof(Color), "White"));
                Console.WriteLine(Enum.IsDefined(typeof(Color), (byte)10));
            }
            {
                try
                {
                    SetColor((Color)(byte)11);
                }
                catch (ArgumentOutOfRangeException e)
                {
                    Console.WriteLine(e.Message);
                }
            }
        }

        private enum Color : byte
        {
            White,
            Red,
            Green,
            Blue,
            Orange
        }

        private static void SetColor(Color c)
        {
            if (!Enum.IsDefined(typeof(Color), c))
            {
                throw new ArgumentOutOfRangeException("c", c, "Invalid Color value.");
            }
        }

        internal static void C02()
        {
            {
                string file = Assembly.GetEntryAssembly().Location;
                FileAttributes attributes = File.GetAttributes(file);
                Console.WriteLine("Is {0} hidden? {1}", file, (attributes & FileAttributes.Hidden) != 0);
                //File.SetAttributes(file, FileAttributes.ReadOnly | FileAttributes.Hidden);
                Actions actions = Actions.Read | Actions.Write;
                Console.WriteLine(actions.ToString());
            }
            {

            }
        }

        [Flags]
        private enum Actions
        {
            None = 0,
            Read = 0x0001,
            Write = 0x0002,
            Delete = 0x0004,
            Query = 0x0008,
            Sync = 0x0010
        }

        internal static void C03()
        {
            FileAttributes fa = FileAttributes.System;
            fa = fa.Set(FileAttributes.ReadOnly);
            fa = fa.Clear(FileAttributes.System);
            fa.ForEach(f => Console.WriteLine(f));
        }
    }

    internal static class FileAttributesExtensionMethods
    {
        internal static bool IsSet(this FileAttributes flags, FileAttributes flagToTest)
        {
            if (flagToTest == 0)
            {
                throw new ArgumentOutOfRangeException("flagToTest", "Value must not be 0");
            }
            return (flags & flagToTest) == flagToTest;
        }

        internal static bool IsClear(this FileAttributes flags, FileAttributes flagToTest)
        {
            if (flagToTest == 0)
            {
                throw new ArgumentOutOfRangeException("flagToTest", "Value must not be 0");
            }
            return !IsSet(flags, flagToTest);
        }

        internal static bool AnyFlagsSet(this FileAttributes flags, FileAttributes testFlags)
        {
            return (flags | testFlags) != 0;
        }

        internal static FileAttributes Set(this FileAttributes flags, FileAttributes setFlags)
        {
            return flags | setFlags;
        }

        internal static FileAttributes Clear(this FileAttributes flags, FileAttributes clearFlags)
        {
            return flags & ~clearFlags;
        }

        internal static void ForEach(this FileAttributes flags, Action<FileAttributes> processFlag)
        {
            if (processFlag == null)
            {
                throw new ArgumentNullException("processFlag");
            }
            for (int i = 1; i != 0; i <<= 1)
            {
                int temp = ((int)flags) & i;
                if (temp != 0)
                {
                    processFlag((FileAttributes)temp);
                }
            }
        }
    }
}
